#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
@file: lead.py
@time: 2024-07-14 23:09
@desc: 
"""
from flask import Blueprint, request, jsonify, send_file
from io import BytesIO
import pandas as pd
import traceback
from tools import log_operations, token_required
from global_scope import MAX_PAGE_SIZE, get_db, leads_sheet_name, ips_sheet_name
from common_tools import apply_formatting
from datetime import datetime
from project_model import Lead
from tools import get_leads_df, excel_to_leads, get_ips_df, excel_to_ips
from common_tools import to_dict

db = get_db()
lead_bp = Blueprint('lead', __name__, url_prefix='/leads')


@lead_bp.route('', methods=['POST'])
@log_operations
@token_required
def create_lead():
    data = request.json
    pn = data.get('pn')
    if not pn:
        return jsonify({"code": 1, "message": "Phone number is required"}), 400

    lead = Lead.query.filter_by(pn=pn).first()
    if lead:
        return jsonify({"code": 1, "message": "Phone number already exists"}), 400

    new_lead = Lead(
        from_source=data.get('from_source'),
        ppn=data.get('ppn'),
        pn=data.get('pn'),
        cc=data.get('cc'),
        pi=data.get('pi'),
        remark=data.get('remark')
    )
    db.session.add(new_lead)
    db.session.commit()
    return jsonify({"code": 0, "message": "OK", "data": new_lead.id, "originUrl": request.url}), 200


@lead_bp.route('/<int:lead_id>', methods=['DELETE'])
@log_operations
@token_required
def delete_lead(lead_id):
    lead = Lead.query.get_or_404(lead_id)
    db.session.delete(lead)
    db.session.commit()
    return jsonify({"code": 0, "message": "OK", "data": lead_id, "originUrl": request.url}), 200


@lead_bp.route('/<int:lead_id>', methods=['PUT'])
@log_operations
@token_required
def update_lead(lead_id):
    data = request.json
    lead = Lead.query.get_or_404(lead_id)
    lead.from_source = data.get('from_source', lead.from_source)
    lead.ppn = data.get('ppn', lead.ppn)
    lead.pn = data.get('pn', lead.pn)
    lead.cc = data.get('cc', lead.cc)
    lead.pi = data.get('pi', lead.pi)
    lead.remark = data.get('remark', lead.remark)
    lead.updateTime = datetime.utcnow()
    db.session.commit()
    return jsonify({"code": 0, "message": "OK", "data": lead_id, "originUrl": request.url}), 200


@lead_bp.route('/<int:lead_id>', methods=['GET'])
@log_operations
@token_required
def get_lead(lead_id):
    lead = Lead.query.get_or_404(lead_id)
    return jsonify({"code": 0, "message": "OK", "data": lead.to_dict(), "originUrl": request.url}), 200


@lead_bp.route('', methods=['GET'])
@log_operations
@token_required
def list_leads():
    page = request.args.get('page', 1, type=int)
    page_size = min(request.args.get('pageSize', MAX_PAGE_SIZE, type=int), MAX_PAGE_SIZE)
    pn = request.args.get('pn', '')
    cc = request.args.get('cc', '')
    from_source = request.args.get('from_source', '')

    query = Lead.query
    if pn:
        query = query.filter(Lead.pn.contains(pn))
    if cc:
        query = query.filter(Lead.cc == cc)
    if from_source:
        query = query.filter(Lead.from_source.contains(from_source))

    pagination = query.paginate(page=page, per_page=page_size, error_out=False)
    leads = pagination.items
    # 构造响应体，包括分页数据和总数
    response_data = {
        "pageData": [to_dict(
            id=lead.id, from_source=lead.from_source, ppn=lead.ppn, pn=lead.pn, cc=lead.cc,
            pi=lead.pi, times=lead.times, remark=lead.remark, createTime=lead.createTime,
            updateTime=lead.updateTime,
            ips=[to_dict(
                id=ip.id, from_source=ip.from_source, ip=ip.ip, remark=ip.remark,
                createTime=ip.createTime, updateTime=ip.updateTime,
                city=ip.city, province=ip.province, country=ip.country,
                li=ip.li, times=ip.times,
            ) for ip in lead.ips]
        ) for lead in leads],
        "total": pagination.total,
    }
    return jsonify({
        "code": 0,
        "message": "OK",
        "data": response_data,
        "originUrl": request.url,
        "total": pagination.total,
        "pages": pagination.pages,
        "current_page": pagination.page
    }), 200


@lead_bp.route('/download', methods=['GET'])
@log_operations
@token_required
def download_leads():
    output = BytesIO()
    with pd.ExcelWriter(output, engine='openpyxl') as writer:
        df_objs = [
            (get_ips_df(), ips_sheet_name),
            (get_leads_df(), leads_sheet_name)
        ]
        # 写入数据
        for df, sheet_name in df_objs:
            df.to_excel(writer, index=False, sheet_name=sheet_name)
            apply_formatting(writer.sheets[sheet_name], df)
    output.seek(0)
    return send_file(output, download_name="leads.xlsx", as_attachment=True)


@lead_bp.route('/upload', methods=['POST'])
@log_operations
@token_required
def upload_leads():
    if 'file' not in request.files:
        return jsonify({"code": 1, "message": "No file part"}), 400

    file = request.files['file']
    if file.filename == '':
        return jsonify({"code": 1, "message": "No selected file"}), 400

    try:
        excel_to_ips(file, request)
        new_records, updated_records = excel_to_leads(file, request)
        return jsonify({
            "code": 0,
            "message": f"Leads uploaded successfully: {new_records} added, {updated_records} updated"
        }), 201
    except Exception as e:
        tb = traceback.format_exc()
        request.trace_logger.error(f"Exception occurred: {str(e)}\n{tb}")
        return jsonify({"code": 1, "message": str(e)}), 500
